
#include "TcpSocket.h"

extern "C"
{
	static pj_bool_t tcp_on_data_read(pj_activesock_t *asock,void *data,
					pj_size_t size,pj_status_t status,pj_size_t *remainder)
	{
		TcpSocket *p_sock = (TcpSocket*) pj_activesock_get_user_data(asock);
		return p_sock->OnDataRead(data,size,status,remainder);
	}

	static pj_bool_t tcp_on_data_sent(pj_activesock_t *asock,pj_ioqueue_op_key_t *op_key,
					pj_ssize_t sent)
	{
		TcpSocket *p_sock = (TcpSocket*) pj_activesock_get_user_data(asock);
		return p_sock->OnDataSend(op_key,sent);
	}

	static pj_bool_t tcp_on_connect_complete(pj_activesock_t *asock,pj_status_t status)
	{
		TcpSocket *p_sock = (TcpSocket*) pj_activesock_get_user_data(asock);
		return p_sock->OnConnect(status);
	}

	static pj_bool_t tcp_on_accept_complete(pj_activesock_t *asock,pj_sock_t newsock,const pj_sockaddr_t *src_addr,int src_addr_len)
	{
		TcpSocket *p_sock = (TcpSocket*) pj_activesock_get_user_data(asock);
		return p_sock->OnAccept(newsock,src_addr,src_addr_len);
	}

}

pj_bool_t TcpSocket::OnAccept(pj_sock_t newsock,const pj_sockaddr_t *src_addr,int src_addr_len)
{
	return OnAccept(p_proactor,newsock,src_addr,src_addr_len);
}

TcpSocket::TcpSocket(Proactor* proactor,pj_sock_t newsock):BaseSocket(proactor,PJ_SOCK_STREAM)
{
	sock = newsock;
    pj_bzero(&cb, sizeof(cb));

	cb.on_data_read = &tcp_on_data_read;
    cb.on_data_sent = &tcp_on_data_sent;
}

TcpSocket::TcpSocket(Proactor* proactor,char* remoteip,unsigned short remoteport):BaseSocket(proactor,PJ_SOCK_STREAM)
{
	pj_status_t status;
	pj_sock_socket(pj_AF_INET(),pj_SOCK_STREAM(),0,&sock);

	pj_sockaddr_init(PJ_AF_INET, &addr, &pj_str(remoteip), remoteport);
	
    pj_bzero(&cb, sizeof(cb));

	cb.on_data_read = &tcp_on_data_read;
    cb.on_data_sent = &tcp_on_data_sent;
	cb.on_connect_complete = &tcp_on_connect_complete;
	cb.on_accept_complete = &tcp_on_accept_complete;
}


TcpSocket::TcpSocket(Proactor* proactor,unsigned short listenport,int reuse):BaseSocket(proactor,PJ_SOCK_STREAM)
{
	pj_status_t status;
	pj_sock_socket(pj_AF_INET(),pj_SOCK_STREAM(),0,&sock);
	
	status = pj_sock_bind_in(sock,0,listenport);
	if (status != PJ_SUCCESS)
	{
		pj_sock_close(sock);
		return ;
	}
	status = pj_sock_listen(sock,100);

    pj_bzero(&cb, sizeof(cb));

	cb.on_accept_complete = &tcp_on_accept_complete;

}

TcpSocket::~TcpSocket()
{

}
pj_bool_t TcpSocket::OnDataRead(void *data,pj_size_t size,int status,pj_size_t* remainder)
{
	if (status != PJ_SUCCESS)
	{
		OnClose(status);
		return PJ_FALSE;
	}
	return PJ_TRUE;
}

int TcpSocket::Connect()
{
	pj_status_t status;

	status = pj_activesock_start_connect(p_asock,p_proactor->pool,
			(pj_sockaddr_t*)&addr,pj_sockaddr_get_len(&addr));

	return status;

}

//int TcpSocket::Bind(unsigned short remoteport)
//{
//	pj_status_t status;
//	pj_sock_socket(pj_AF_INET(),pj_SOCK_STREAM(),0,&sock);
//	status = pj_sock_bind_in(sock,0,remoteport);
//	if (status != PJ_SUCCESS)
//	{
//		pj_sock_close(sock);
//		return status;
//	}
//	status = pj_sock_listen(sock,10);
//	return status;
//}

int TcpSocket::Accept()
{
	pj_status_t status;
	if (!p_asock)
		return -1;

	status = pj_activesock_start_accept(p_asock,p_proactor->pool);

	return status;

}


int TcpSocket::Send(const char* buff,long &size,int flags)
{
	pj_status_t status;
	status = pj_activesock_send(p_asock,&send_key,buff,&size,flags);

	return status;
}

int TcpSocket::Recv(long size,int flags)
{
	pj_status_t status;
	status = pj_activesock_start_read(p_asock,p_proactor->pool,size,flags);

	return status;
}

//int TcpSocket::Close()
//{
//	pj_status_t status;
//	status = pj_activesock_close(p_asock);
//
//	return status;
//}


